#include <functional>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <iterator>
#include <iostream>
#include <map>


class point { 
public: 
    point(double x, double y) : m_x(x), m_y(y) { } 
    double mag() const {return sqrt(m_x * m_x + m_y * m_y); } 
    double dist(const point& p) const {
        return sqrt(pow(m_x - p.m_x, 2)+ pow(m_y - p.m_y, 2)); 
    } 
private: 
   double m_x; 
   double m_y;
};

void test_mem_fun_reference_to_object()
{
    std::vector<point> v; 
    v.push_back(point(3, 4));
    v.push_back(point(5, 12)); 
    v.push_back(point(8, 15)); 
    transform(v.begin(), v.end(),
              std::ostream_iterator<double>(std::cout, "\t"),
              std::tr1::mem_fn(&point::mag));
    std::cout << std::endl;
}
void test_mem_fun_pointer_to_object()
{
    std::vector<const point *> p;
    std::vector<point> v; 
    v.push_back(point(3, 4));
    v.push_back(point(5, 12)); 
    v.push_back(point(8, 15));     
    for (std::vector<point>::const_iterator i = v.begin();
         i != v.end(); ++i) {
        p.push_back(&*i);
    }
    transform(p.begin(), p.end(),
              std::ostream_iterator<double>(std::cout, "\t"),
              std::tr1::mem_fn(&point::mag));
    std::cout << std::endl;
}
void test_mem_fun_shared_ptr_to_object()
{
    using std::tr1::shared_ptr;
    using std::vector;
    
    vector<shared_ptr<point> > s; 
    s.push_back(shared_ptr<point>(new point(3, 4))); 
    s.push_back(shared_ptr<point>(new point(5, 12))); 
    s.push_back(shared_ptr<point>(new point(8, 15))); 
    transform(s.begin(), s.end(),
              std::ostream_iterator<double>(std::cout,"\t"),
              std::tr1::mem_fn(&point::mag));
    std::cout << std::endl;
}

void test_mem_fun_point_to_data_member()
{

    std::map<std::string, bool> m;
    m["cat"] = true;
    m["dog"] = false;
    m["kitty"] = true;
    std::cout << count_if(m.begin(), m.end(),
                          std::tr1::mem_fn(
                              &std::pair<const std::string, bool>::second))
              << std::endl;
}
int main()
{
    test_mem_fun_reference_to_object();
    test_mem_fun_pointer_to_object();
    test_mem_fun_shared_ptr_to_object();
    test_mem_fun_point_to_data_member();
}
